﻿using ProjScan.Config;
using ProjScan.RecordManager;
using ProjScan.RecordManager.AssetData;
using ProjScan.ScanRule.Attr;
using ProjScan.Submodules.Art_Assets_Check;
using ProjScan.Tools;
using System;
using System.IO;
using UnityEngine;
using UnityEngine.Rendering;

namespace ProjScan.ScanRule.ArtAssets.Mesh
{
    [ArtAssetRuleAttr]
    internal class HardedgeUVSeamConsistency : RecordRuleImp<MeshRenderingAssetData, MeshRenderingRecordManager>
    {
        private int threshold = 32;

        private string picDataFolder = null;

        protected override bool UseAssetDataCSVHeader => false;

        public HardedgeUVSeamConsistency()
        {
            ArtAssetsCheckConfig artAssetsCheckConfig = Singleton<ConfigMgr>.Instance.GetConfig<ArtAssetsCheckConfig>() as ArtAssetsCheckConfig;
            threshold = artAssetsCheckConfig.hardedgeUVSeamThreshold;
            picDataFolder = ToolsHelper.GetScanOutPut() + "/HardedgeUVSeamConsistency";
            if (!Directory.Exists(picDataFolder))
            {
                Directory.CreateDirectory(picDataFolder);
            }
        }

        public override void CheckDirSetted()
        {
            if (SeparateDirSettingsEnabled)
            {
                if (target_configs == null || target_configs.Length == 0)
                {
                    ScanLog.UnityLogError("美术资源检测规则 " + GetType().Name + " 执行失败，未设置目标文件夹");
                }

                if (target_configs.Length == 1 && target_configs[0].assetPath.StartsWith("Assets/ArtCheckFolder"))
                {
                    ScanLog.UnityLogError("美术资源检测规则 " + GetType().Name + " 执行失败，未设置目标文件夹");
                }
            }
        }

        public static bool CheckHardEdgeUVSeam(UnityEngine.Mesh uvMesh, out Texture2D guideLineTexture, int uvThreshold)
        {
            RenderTexture renderTexture = ShaderUtility.RenderTextureFromMesh(uvMesh, 512, "Hidden/UvUnwrap");
            RenderTexture renderTexture2 = new RenderTexture(512, 512, 32, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear)
            {
                enableRandomWrite = true
            };
            renderTexture2.Create();
            ComputeBuffer computeBuffer = new ComputeBuffer(1, 4, ComputeBufferType.Counter);
            computeBuffer.SetCounterValue(0u);
            ShaderUtility.LoadComputeShader().SetBuffer(ShaderUtility.FetchKernelK2(), "v13", computeBuffer);
            ShaderUtility.LoadComputeShader().SetTexture(ShaderUtility.FetchKernelK2(), "v11", renderTexture);
            ShaderUtility.LoadComputeShader().SetTexture(ShaderUtility.FetchKernelK2(), "T1", renderTexture2);
            ShaderUtility.LoadComputeShader().Dispatch(ShaderUtility.FetchKernelK2(), 64, 64, 1);
            renderTexture.Release();
            ComputeBuffer computeBuffer2 = new ComputeBuffer(1, 4, ComputeBufferType.IndirectArguments);
            ComputeBuffer.CopyCount(computeBuffer, computeBuffer2, 0);
            int[] array = new int[1];
            computeBuffer2.GetData(array);
            computeBuffer2.Release();
            computeBuffer.Release();
            if (array[0] > uvThreshold)
            {
                RenderTexture active = RenderTexture.active;
                RenderTexture.active = renderTexture2;
                guideLineTexture = new Texture2D(512, 512);
                guideLineTexture.ReadPixels(new Rect(0f, 0f, 512f, 512f), 0, 0);
                guideLineTexture.Apply();
                RenderTexture.active = active;
                renderTexture2.Release();
                return true;
            }

            guideLineTexture = null;
            return false;
        }

        public override bool CheckSupportability(out string msg)
        {
            if (!SystemInfo.supportsComputeShaders)
            {
                msg = "请将Standalone Windows平台的Graphics API设置成DX，有些Unity版本还需将Edit->Graphics Emulation设置为No Emulation。";
                return false;
            }

            if (Singleton<ScanInfo>.Instance.graphicsDeviceType == GraphicsDeviceType.Direct3D11 || Singleton<ScanInfo>.Instance.graphicsDeviceType == GraphicsDeviceType.Direct3D12)
            {
                msg = "请将Standalone Windows平台的Graphics API设置成DX，有些Unity版本还需将Edit->Graphics Emulation设置为No Emulation。";
                return true;
            }

            msg = "请将Standalone Windows平台的Graphics API设置成DX，有些Unity版本还需将Edit->Graphics Emulation设置为No Emulation。";
            return false;
        }

        protected override string GetDetailCSVHeader()
        {
            return base.GetDetailCSVHeader() + ",边界一致性检验结果图";
        }

        protected override string GetDetailInfo(MeshRenderingAssetData assetData, string failedInfo)
        {
            string str = string.IsNullOrEmpty(assetData.hardedgeUVSeamConsistencyPicPath) ? string.Empty : ("image://" + assetData.hardedgeUVSeamConsistencyPicPath);
            return base.GetDetailInfo(assetData, failedInfo) + str;
        }

        protected override bool IsOK(MeshRenderingAssetData assetData)
        {
            Texture2D guideLineTexture = null;
            bool flag = false;
            try
            {
                flag = !CheckHardEdgeUVSeam(assetData.asset, out guideLineTexture, threshold);
            }
            catch (Exception exception_)
            {
                ScanLog.Instance.LogException(exception_, "HardedgeUVSeamConsistency.CheckHardEdgeUVSeam", "");
                return false;
            }

            if (!flag)
            {
                assetData.hardedgeUVSeamConsistencyPicPath = picDataFolder + "/" + assetData.id + ".png";
                string path = picDataFolder + "/" + assetData.id;
                try
                {
                    ShaderUtility.SaveTexture(path, guideLineTexture);
                }
                catch (Exception exception_2)
                {
                    ScanLog.Instance.LogException(exception_2, "HardedgeUVSeamConsistency.Tex2Png", "");
                    return false;
                }
            }

            return flag;
        }
    }
}